﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Markup;
using NetBay.Core.BusinessEntities.Workflow;
using NetBay.Core.BusinessEntities;
using Rio.Framework.Pages.Helpers;
using Rio.Framework.Pages.Helpers.Converter;
using Rio.Framework.Pages.Manager;
using Rio.Framework.Pages.Workflow.BaseClass;
using Rio.Framework.Pages.Workflow.Models;
using Telerik.Windows.Controls;
using Rio.Applications.Web.Services;
using Rio.Framework.Pages.Context;
using Telerik.Windows.Data;
using Rio.Framework.Pages.AppCode.Helpers;
using GalaSoft.MvvmLight.Command;
using System.ServiceModel.DomainServices.Client;
using Rio.Framework.Localisation;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows;
using System.Collections.ObjectModel;

namespace Rio.Framework.Pages.Workflow
{
    public partial class WorkflowInstanceList : WorkflowInstanceListBase
    {

        public Organization Organization
        {
            get { return (Organization)GetValue(OrganizationProperty); }
            set { SetValue(OrganizationProperty, value); }
        }
        public static readonly DependencyProperty OrganizationProperty =
            DependencyProperty.Register("Organization", typeof(Organization), typeof(WorkflowInstanceList), null);

        public FolderType FolderType
        {
            get { return (FolderType)GetValue(FolderTypeProperty); }
            set { SetValue(FolderTypeProperty, value); }
        }
        public static readonly DependencyProperty FolderTypeProperty =
            DependencyProperty.Register("FolderType", typeof(FolderType), typeof(WorkflowInstanceList), null);

        public WorkflowInstanceListMode Mode
        {
            get { return (WorkflowInstanceListMode)GetValue(ModeProperty); }
            set { SetValue(ModeProperty, value); }
        }
        public static readonly DependencyProperty ModeProperty =
            DependencyProperty.Register("Mode", typeof(WorkflowInstanceListMode), typeof(WorkflowInstanceList), new System.Windows.PropertyMetadata(WorkflowInstanceListMode.Normal));
        

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="WorkflowInstanceList"/> class.
        /// </summary>
        public WorkflowInstanceList()
        {
            InitializeComponent();

            Dispatcher.BeginInvoke(new Action(() => this.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name)));

            InitLabels();

            FlowActionPerfomedCommand = new RelayCommand<string>(
                FlowActionPerformed,
                CanExecuteFlowAction);

            GridViewWorkflowMessages.AddHandler(GridViewCellBase.CellDoubleClickEvent, new EventHandler<RadRoutedEventArgs>(OnGridViewCellDoubleClick), true);
        }

        #endregion

        #region Methods

        /// <summary>
        /// Called when [grid view cell double click].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="Telerik.Windows.RadRoutedEventArgs"/> instance containing the event data.</param>
        private void OnGridViewCellDoubleClick(object sender, RadRoutedEventArgs args)
        {
            DisplaySelectedWorkflowInstance();
        }

        /// <summary>
        /// Handles the Loaded event of the HistoryGridView control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void HistoryGridViewLoaded(object sender, RoutedEventArgs e)
        {
            RadGridView historyGridView = sender as RadGridView;

            if (historyGridView != null)
            {
                historyGridView.SelectedItem = null;
            }

            SplashScreenManager.Wait(this);
            if (historyGridView != null)
            {
                WorkflowInstance documentStateSource = (WorkflowInstance)historyGridView.DataContext;
                BusinessEntitiesDomainContext ds = GlobalWebContext.BusinessEntitiesDomainContext;
                var query = ds.GetWorkflowHistoByInstanceIdQuery(
                    documentStateSource.Identifier);
                ds.Load(
                    query,
                    result =>
                    {
                        SplashScreenManager.Stop(this);
                        if (!result.HasError && result.Entities != null)
                        {
                            historyGridView.ItemsSource = new QueryableCollectionView(result.Entities.Reverse().ToList());
                        }
                    },
                    null);
            }
        }

        /// <summary>
        /// Handles the SelectionChanged event of the GridViewWorkflowMessages control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Telerik.Windows.Controls.SelectionChangeEventArgs"/> instance containing the event data.</param>
        private void GridViewWorkflowMessagesSelectionChanged(object sender, SelectionChangeEventArgs e)
        {
            RadGridView gridViewSource = sender as RadGridView;

            if (gridViewSource != null)
            {
                SelectedWorkflowInstances = new ObservableCollection<WorkflowInstance>(
                    gridViewSource.SelectedItems.Cast<WorkflowInstance>());
            }
        }

        /// <summary>
        /// Determines whether this instance [can execute flow action].
        /// </summary>
        /// <returns>
        ///   <c>true</c> if this instance [can execute flow action]; otherwise, <c>false</c>.
        /// </returns>
        private bool CanExecuteFlowAction(string buttonName)
        {
            bool canExecute = false;

            switch (buttonName.ToLowerInvariant())
            {
                case "delete":
                    canExecute = (Mode == WorkflowInstanceListMode.Normal && SelectedWorkflowInstances != null && SelectedWorkflowInstances.Count > 0);
                    DeleteContextMenuWkf.IsEnabled = canExecute;
                    break;
                case "display":
                    canExecute = (SelectedWorkflowInstances != null && SelectedWorkflowInstances.Count == 1);
                    DisplayMessageContextMenuWkf.IsEnabled = canExecute;
                    break;
                case "refresh":
                    if (Mode == WorkflowInstanceListMode.Normal)
                        canExecute = _selectedDataItemTreeView != null;
                    else
                        canExecute = (FolderType != null && _selectedDataItemTreeView != null);
                    break;
                case "remind":
                    canExecute = (Mode == WorkflowInstanceListMode.Administration && SelectedWorkflowInstances != null && SelectedWorkflowInstances.Count == 1);
                    break;
            }

            return canExecute;
        }

        /// <summary>
        /// Flows the action performed.
        /// </summary>
        private void FlowActionPerformed(string buttonName)
        {
            switch (buttonName.ToLowerInvariant())
            {
                case "delete":
                    DeleteSelectedWorkflowInstances();
                    break;
                case "display":
                    DisplaySelectedWorkflowInstance();
                    break;
                case "refresh":
                    RefreshWorkflowInstances();
                    break;
                case "remind":
                    OpenRemindChildWindow();
                    break;
            }
        }

        /// <summary>
        /// Refreshes the workflow instances.
        /// </summary>
        public void RefreshWorkflowInstances(DataItemTreeView d = null)
        {
            if (d != null)
                _selectedDataItemTreeView = d;

            switch (Mode)
            {
                case WorkflowInstanceListMode.Normal:
                    LoadWorkflowInstancesNormalMode();
                    break;
                case WorkflowInstanceListMode.Administration:
                    LoadWorkflowInstancesAdminMode();
                    break;
            }
        }

        /// <summary>
        /// Loads the workflow instances admin mode.
        /// </summary>
        private void LoadWorkflowInstancesAdminMode()
        {
            if (_selectedDataItemTreeView == null)
                return;


            bool completed = _selectedDataItemTreeView.SubItemType == WorkflowTreeSubItemType.Completed;
            BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;
            SplashScreenManager.Wait(this);

            var getWorkflowInstancesByFldTypeIdQuery = businessEntitiesDomainContext.GetWorkflowInstancesByFldTypeIdQuery(Organization.Identifier, FolderType.Identifier, completed);
            businessEntitiesDomainContext.Load(
                getWorkflowInstancesByFldTypeIdQuery,
                LoadWorkflowInstancesCallBack,
                null);
        }

        /// <summary>
        /// Loads the workflow instances normal mode.
        /// </summary>
        private void LoadWorkflowInstancesNormalMode()
        {
            bool completed = _selectedDataItemTreeView.SubItemType == WorkflowTreeSubItemType.Completed;

            BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;

            SplashScreenManager.Wait(this);

            switch (_selectedDataItemTreeView.ItemType)
            {
                case WorkflowTreeItemType.Reception:

                    var getWorkflowInstancesByReceiverIdQuery = businessEntitiesDomainContext.GetWorkflowInstancesByReceiverIdQuery(GlobalWebContext.CurrentUser.UserId, _selectedDataItemTreeView.FolderTypeId, completed);
                    businessEntitiesDomainContext.Load(
                        getWorkflowInstancesByReceiverIdQuery,
                        LoadWorkflowInstancesCallBack,
                        null);

                    break;
                case WorkflowTreeItemType.Send:

                    var getWorkflowInstancesBySenderIdQuery = businessEntitiesDomainContext.GetWorkflowInstancesBySenderIdQuery(GlobalWebContext.CurrentUser.UserId, _selectedDataItemTreeView.FolderTypeId, completed);
                    businessEntitiesDomainContext.Load(
                        getWorkflowInstancesBySenderIdQuery,
                        LoadWorkflowInstancesCallBack,
                        null);

                    break;
            }
        }

        /// <summary>
        /// Loads the workflow instances call back.
        /// </summary>
        /// <param name="result">The result.</param>
        private void LoadWorkflowInstancesCallBack(LoadOperation<WorkflowInstance> result)
        {
            if (!result.HasError)
            {
                if (result.Entities.Count() > 0)
                {
                    LoadWorkflowFoldersIndexColumns();
                    LoadWorkflowFoldersValuesColumns(result.Entities);
                }
                else
                {
                    ClearDynamicColumns();
                    WorkflowInstances = null;
                    _selectedDataItemTreeView = null;
                }
            }
            else
            {
                _selectedDataItemTreeView = null;
                LoggerHelper.Send(this.GetType().Name, "EXCEPTION LoadWorkflowInstancesCallBack : " + Environment.NewLine + result.Error.Message);
            }
            SplashScreenManager.Stop(this);
        }

        /// <summary>
        /// Loads the folder type index columns.
        /// </summary>
        public void LoadWorkflowFoldersIndexColumns()
        {
            try
            {
                SplashScreenManager.Wait(this);
                ClearDynamicColumns();

                //Load dynamic index columns
                FolderType folderType = Mode == WorkflowInstanceListMode.Normal ? GlobalWebContext.CurrentUser.GroupList.SelectMany(g => g.OrganizationList).SelectMany(o => o.FolderTypesList).FirstOrDefault(ft => ft.Identifier == _selectedDataItemTreeView.FolderTypeId) : FolderType;
                AddFolderIndexColumnsToGrid(folderType, GridViewWorkflowMessages, GlobalWebContext.AddFlowIndexInFirst);
            }
            finally
            {
                SplashScreenManager.Stop(this);
            }
        }

        /// <summary>
        /// Clears the dynamic columns.
        /// </summary>
        private void ClearDynamicColumns()
        {
            List<GridViewColumn> columns = new List<GridViewColumn>();

            if (GlobalWebContext.AddFlowIndexInFirst)
            {
                foreach (var column in GridViewWorkflowMessages.Columns)
                {
                    if (column.UniqueName != null && column.UniqueName.StartsWith("IDX"))
                    {
                        columns.Add(column);
                    }
                }
            }
            else
            {
                for (int i = 10; i < GridViewWorkflowMessages.Columns.Count; i++)
                    columns.Add(GridViewWorkflowMessages.Columns[i]);
            }

            GridViewWorkflowMessages.Columns.RemoveItems(columns);
        }

        /// <summary>
        /// Inits the labels.
        /// </summary>
        private void InitLabels()
        {
            GridViewWorkflowMessages.Columns["GridViewWorkflowMessages_StateLabel"].Header = Resx.GetLabel(ResxWorkflow.State);
            GridViewWorkflowMessages.Columns["GridViewWorkflowMessages_Sender"].Header = Resx.GetLabel(ResxFlowPage.SENDER);
            GridViewWorkflowMessages.Columns["GridViewWorkflowMessages_Date"].Header = Resx.GetLabel(ResxFlowPage.SENDINGDATE);
            GridViewWorkflowMessages.Columns["GridViewWorkflowMessages_FlowName"].Header = Resx.GetLabel(ResxWorkflow.FlowName);
            GridViewWorkflowMessages.Columns["GridViewWorkflowMessages_Event"].Header = Resx.GetLabel(ResxWorkflow.EventSource);
            GridViewWorkflowMessages.Columns["GridViewWorkflowMessages_SendTo"].Header = Resx.GetLabel(ResxWorkflow.SendTo);
            GridViewWorkflowMessages.Columns["GridViewWorkflowMessages_Receivers"].Header = Resx.GetLabel(ResxWorkflow.Receiver);
        }

        /// <summary>
        /// Loads the workflow folders values columns.
        /// </summary>
        private void LoadWorkflowFoldersValuesColumns(IEnumerable<WorkflowInstance> list)
        {
            WorkflowInstances = new QueryableCollectionView(list);
        }

        /// <summary>
        /// Sets the grid view row as read.
        /// </summary>
        protected override void SetGridViewRowAsRead()
        {
            if (GridViewWorkflowMessages.CurrentCell != null && GridViewWorkflowMessages.CurrentCell.ParentRow != null)
            {
                GridViewWorkflowMessages.CurrentCell.ParentRow.FontWeight = FontWeights.Normal;
            }
        }

        /// <summary>
        /// Handles the Loaded event of the userControl control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void UserControlLoaded(object sender, RoutedEventArgs e)
        {
            buttonRemind.Visibility = Mode == WorkflowInstanceListMode.Normal ? Visibility.Collapsed : Visibility.Visible;
        }

        /// <summary>
        /// Handles the Click event of the DisplayMessageContextMenuWkf control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Telerik.Windows.RadRoutedEventArgs"/> instance containing the event data.</param>
        private void DisplayMessageContextMenuWkfClick(object sender, RadRoutedEventArgs e)
        {
            DisplaySelectedWorkflowInstance();
        }

        /// <summary>
        /// Handles the Click event of the DeleteContextMenuWkf control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Telerik.Windows.RadRoutedEventArgs"/> instance containing the event data.</param>
        private void DeleteContextMenuWkfClick(object sender, RadRoutedEventArgs e)
        {
            DeleteSelectedWorkflowInstances();
        }

        /// <summary>
        /// Displays the selected workflow instance.
        /// </summary>
        protected void DisplaySelectedWorkflowInstance()
        {
            if (SelectedWorkflowInstances != null && SelectedWorkflowInstances.Count > 0)
            {

                SplashScreenManager.Wait(this);

                long organizationId, folderTypeId;
                if (Mode == WorkflowInstanceListMode.Normal)
                {
                    folderTypeId = _selectedDataItemTreeView.FolderTypeId;
                    organizationId = _selectedDataItemTreeView.OrganizationId;
                }
                else
                {
                    folderTypeId = FolderType.Identifier;
                    organizationId = Organization.Identifier;
                }

                BusinessEntitiesDomainContext businessEntitiesDomainContext = GlobalWebContext.BusinessEntitiesDomainContext;
                var query = businessEntitiesDomainContext.GetFolderQuery(
                    organizationId,
                    folderTypeId,
                    SelectedWorkflowInstances.First().FolderId,
                    String.Empty,
                    null);

                businessEntitiesDomainContext.Load(
                    query,
                    r =>
                    {
                        if (!r.HasError && r.Entities != null && r.Entities.Count() > 0)
                        {
                            Cursor = Cursors.Arrow;

                            if (String.Equals(r.Entities.First().State, "SUPPR", StringComparison.InvariantCultureIgnoreCase))
                            {
                                
                                SplashScreenManager.Stop(this);
                                MessageBoxChildWindow window = new MessageBoxChildWindow(
                                    String.Empty,
                                    Resx.GetLabel(ResxWorkflow.Workflow_FolderSuppr_Error),
                                    MessageBoxButtons.Ok,
                                    MessageBoxIcon.Information);

                                window.ShowDialog();



                            }
                            else
                            {
                                SetGridViewRowAsRead();

                                OnWorkflowInstanceDisplaying(r.Entities.First(), SelectedWorkflowInstances.First());
                            }

                        }
                    },
                    null);
            }
        }

        /// <summary>
        /// Deletes the selected workflow instances.
        /// </summary>
        protected void DeleteSelectedWorkflowInstances()
        {
            _selectedWorkflowInstancesToDelete.Clear();

            SplashScreenManager.Wait(this);

            if (Mode == WorkflowInstanceListMode.Normal)
            {
                _selectedWorkflowInstancesToDelete = new Queue<WorkflowInstance>(SelectedWorkflowInstances.Select(p => p).ToList());
                DeleteWorkflowInstance(_selectedWorkflowInstancesToDelete.Dequeue());
            }
        }

        #endregion
    }

}
